package com.jtd.common.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;
import javax.persistence.Column;
import javax.persistence.Table;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.jdbc.core.JdbcTemplate;

import com.jtd.common.dao.IBaseDAO;
import com.jtd.common.dao.ICommonDAO;
import com.jtd.common.dao.exception.DAOException;
import com.jtd.common.dao.exception.UpdateException;

/**
 * @作者 Amos Xu
 * @版本 V1.0
 * @配置 
 * @创建日期 2016年8月25日
 * @项目名称 dsp-common
 * @描述 <p></p>
 */
public abstract class BaseDAO implements IBaseDAO {

	protected Log log = LogFactory.getLog(this.getClass());

	@Resource
	protected ICommonDAO commonDAO;

	@Resource
	protected JdbcTemplate jdbcTemplate;

	/**
	 * 只更新不为null的字段
	 * 
	 * @param object
	 */
	public <T> void updateSelective(T object) {
		if (object == null) {
			throw new UpdateException("待更新的对象为空");
		}
		String tableName = null;
		Class<?> clazz = object.getClass();
		Table table = AnnotationUtils.findAnnotation(clazz, Table.class);
		if (table != null) {
			tableName = table.name();
		}
		if (tableName == null) {
			throw new UpdateException("未找到待更新的表明");
		}
		Method[] methods = clazz.getMethods();
		Map<String, Method> methodMap = new HashMap<String, Method>();
		for (Method method : methods) {
			methodMap.put(method.getName(), method);
		}
		Method getId = methodMap.get("getId");
		if (getId == null) {
			throw new UpdateException("未找到获取主键的方法");
		}
		Long id = null;
		try {
			id = (Long) getId.invoke(object);
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			throw new UpdateException("获取主键失败", e);
		}
		Map<String, Object> toUpdateFields = new HashMap<String, Object>();
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			String fieldName = field.getName();
			String columnName = null;
			Object columnValue = null;

			Column column = AnnotationUtils.getAnnotation(field, Column.class);
			if (column == null) {
				continue;
			}
			if (column.name().equals("")) {
				columnName = field.getName();
			} else {
				columnName = column.name();
			}
			String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
			Method method = methodMap.get(methodName);
			if (method != null) {
				try {
					columnValue = method.invoke(object);
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				}
			}
			if (columnName == null || columnValue == null) {
				continue;
			}
			if (columnValue instanceof Enum) {
				Class<?> c = columnValue.getClass();
				try {
					Method enumMethod = c.getMethod("getCode");
					columnValue = enumMethod.invoke(columnValue);
				} catch (Exception e) {
					throw new UpdateException("获取字段[" + columnName + "]的值失败", e);
				}
			}
			toUpdateFields.put(columnName, columnValue);
		}
		if (toUpdateFields.size() == 0) {
			log.info("没有要更新的字段");
			return;
		}
		// 用jdbctemplate
		StringBuilder updateSql = new StringBuilder("update " + tableName + " set ");
		List<Object> columnValues = new ArrayList<Object>();
		for (Entry<String, Object> toUpdateField : toUpdateFields.entrySet()) {
			String columnName = toUpdateField.getKey();
			Object columnValue = toUpdateField.getValue();
			updateSql.append(columnName).append("=? ,");
			columnValues.add(columnValue);
		}
		updateSql.delete(updateSql.length() - 1, updateSql.length());
		updateSql.append(" where id = ?");
		columnValues.add(id);
		String sql = updateSql.toString();
		log.debug("update sql : " + sql);
		jdbcTemplate.update(sql, columnValues.toArray());
	}

	@Override
	public <T> void save(T object) {
		commonDAO.save(object);
	}

	@Override
	public <T> void update(T object) {
		commonDAO.update(object);
	}

	@Override
	public <T> T get(Class<T> entityClass, Serializable id) {
		return commonDAO.get(entityClass, id);
	}

	@Override
	public <T> void logicDelete(Class<T> entityClass, Serializable id) {
		T obj = commonDAO.get(entityClass, id);
		try {
			Method method = entityClass.getMethod("setDeleteStatus", Boolean.class);
			method.invoke(obj, Boolean.TRUE);
			commonDAO.update(obj);
		} catch (Exception e) {
			throw new DAOException("逻辑删除失败");
		}
	}

	@Override
	public <T> void delete(T object) {
		commonDAO.delete(object);
	}

	@Override
	public <T> void delete(Class<T> entityClass, Serializable id) {
		T  obj = commonDAO.get(entityClass, id);
		if(obj!=null){
			commonDAO.delete(obj);
		}

	}
}
